package cn.metona.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public final class NumberUtils {

    private NumberUtils() {
        throw new UnsupportedOperationException("Utility class");
    }

    // 检查一个数字是否为素数
    public static boolean isPrime(int number) {
        if (number <= 1) {
            return false;
        }
        for (int i = 2; i * i <= number; i++) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }

    // 计算一个数字的阶乘
    public static long factorial(int number) {
        if (number < 0) {
            throw new IllegalArgumentException("Number must be non-negative.");
        }
        long result = 1;
        for (int i = 2; i <= number; i++) {
            result *= i;
        }
        return result;
    }

    // 生成斐波那契数列的前n项
    public static List<Integer> fibonacciSequence(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("Number of terms must be non-negative.");
        }
        List<Integer> sequence = new ArrayList<>();
        if (n >= 1) {
            sequence.add(0);
        }
        if (n >= 2) {
            sequence.add(1);
        }
        for (int i = 2; i < n; i++) {
            sequence.add(sequence.get(i - 1) + sequence.get(i - 2));
        }
        return sequence;
    }

    // 计算两个数字的最大公约数（GCD）
    public static int gcd(int a, int b) {
        while (b != 0) {
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }

    // 计算两个数字的最小公倍数（LCM）
    public static int lcm(int a, int b) {
        return a * (b / gcd(a, b));
    }

    // 判断一个数字是否为回文数
    public static boolean isPalindrome(int number) {
        int reversed = 0;
        int original = number;
        while (original != 0) {
            int digit = original % 10;
            reversed = reversed * 10 + digit;
            original /= 10;
        }
        return number == reversed;
    }

    // 反转一个整数
    public static int reverseNumber(int number) {
        int reversed = 0;
        while (number != 0) {
            int digit = number % 10;
            reversed = reversed * 10 + digit;
            number /= 10;
        }
        return reversed;
    }

    // 将整数转换为二进制字符串
    public static String toBinaryString(int number) {
        return Integer.toBinaryString(number);
    }

    // 将整数转换为八进制字符串
    public static String toOctalString(int number) {
        return Integer.toOctalString(number);
    }

    // 将整数转换为十六进制字符串
    public static String toHexString(int number) {
        return Integer.toHexString(number);
    }

    // 计算一个数字的幂
    public static double power(double base, int exponent) {
        return Math.pow(base, exponent);
    }

    // 计算一个整数的位数
    public static int countDigits(int number) {
        if (number == 0) {
            return 1;
        }
        int count = 0;
        while (number != 0) {
            number /= 10;
            count++;
        }
        return count;
    }

    // 计算一个数字的平方根
    public static double sqrt(double number) {
        if (number < 0) {
            throw new IllegalArgumentException("Number must be non-negative.");
        }
        return Math.sqrt(number);
    }

    // 判断一个数字是否为偶数
    public static boolean isEven(int number) {
        return number % 2 == 0;
    }

    // 判断一个数字是否为完全平方数
    public static boolean isPerfectSquare(int number) {
        if (number < 0) {
            return false;
        }
        int sqrt = (int) Math.sqrt(number);
        return sqrt * sqrt == number;
    }

    // 生成指定范围内的随机整数
    public static int generateRandomNumber(int min, int max) {
        if (min > max) {
            throw new IllegalArgumentException("Min must be less than or equal to max.");
        }
        Random random = new Random();
        return random.nextInt((max - min) + 1) + min;
    }

    // 返回一个数字的绝对值
    public static int abs(int number) {
        return Math.abs(number);
    }

    // 对浮点数进行四舍五入
    public static long round(double number) {
        return Math.round(number);
    }

    // 对浮点数进行向上取整
    public static double ceil(double number) {
        return Math.ceil(number);
    }

    // 对浮点数进行向下取整
    public static double floor(double number) {
        return Math.floor(number);
    }

    // 返回一个数字的符号（-1、0 或 1）
    public static int signum(int number) {
        return Integer.signum(number);
    }

    // 计算排列数 P(n, k)
    public static long permutation(int n, int k) {
        if (n < 0 || k < 0 || k > n) {
            throw new IllegalArgumentException("Invalid arguments for permutation.");
        }
        return factorial(n) / factorial(n - k);
    }

    // 计算组合数 C(n, k)
    public static long combination(int n, int k) {
        if (n < 0 || k < 0 || k > n) {
            throw new IllegalArgumentException("Invalid arguments for combination.");
        }
        return factorial(n) / (factorial(k) * factorial(n - k));
    }

    // 对一个整数进行质因数分解
    public static List<Integer> primeFactors(int number) {
        List<Integer> factors = new ArrayList<>();
        while (number % 2 == 0) {
            factors.add(2);
            number /= 2;
        }
        for (int i = 3; i * i <= number; i += 2) {
            while (number % i == 0) {
                factors.add(i);
                number /= i;
            }
        }
        if (number > 2) {
            factors.add(number);
        }
        return factors;
    }

    // 计算从 1 到 n 的累加和
    public static int sumUpTo(int n) {
        if (n < 0) {
            throw new IllegalArgumentException("Number must be non-negative.");
        }
        return n * (n + 1) / 2;
    }

    // 检查一个整数的特定位是否为 1
    public static boolean isBitSet(int number, int bitPosition) {
        if (bitPosition < 0 || bitPosition >= 32) {
            throw new IllegalArgumentException("Bit position must be between 0 and 31.");
        }
        return (number & (1 << bitPosition)) != 0;
    }

    // 将一个整数的特定位设置为 1
    public static int setBit(int number, int bitPosition) {
        if (bitPosition < 0 || bitPosition >= 32) {
            throw new IllegalArgumentException("Bit position must be between 0 and 31.");
        }
        return number | (1 << bitPosition);
    }

    // 将数字格式化为指定精度的字符串
    public static String formatNumber(double number, int precision) {
        return String.format("%." + precision + "f", number);
    }

    // 计算一个数字的校验和（Luhn 算法）
    public static int calculateLuhnChecksum(long number) {
        String numStr = Long.toString(number);
        int sum = 0;
        boolean alternate = false;
        for (int i = numStr.length() - 1; i >= 0; i--) {
            int digit = Character.getNumericValue(numStr.charAt(i));
            if (alternate) {
                digit *= 2;
                if (digit > 9) {
                    digit = digit - 9;
                }
            }
            sum += digit;
            alternate = !alternate;
        }
        return (sum * 9) % 10;
    }

    public static void main(String[] args) {
        // 测试工具类的方法
        System.out.println("Absolute value of -10: " + abs(-10)); // 10
        System.out.println("Round 3.6: " + round(3.6)); // 4
        System.out.println("Ceil of 3.2: " + ceil(3.2)); // 4.0
        System.out.println("Floor of 3.8: " + floor(3.8)); // 3.0
        System.out.println("Sign of -5: " + signum(-5)); // -1
        System.out.println("Permutation P(5, 2): " + permutation(5, 2)); // 20
        System.out.println("Combination C(5, 2): " + combination(5, 2)); // 10
        System.out.println("Prime factors of 56: " + primeFactors(56)); // [2, 2, 2, 7]
        System.out.println("Sum up to 10: " + sumUpTo(10)); // 55
        System.out.println("Is bit 2 set in 6? " + isBitSet(6, 2)); // true
        System.out.println("Set bit 1 in 4: " + setBit(4, 1)); // 6
        System.out.println("Format 3.14159 to 2 decimal places: " + formatNumber(3.14159, 2)); // 3.14
        System.out.println("Luhn checksum for 7992739871: " + calculateLuhnChecksum(7992739871L)); // 3
    }
}
